/*
 *
 *      Copyright (c) 2018-2025, proj All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the proj developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: proj
 *
 */

package com.ykht.proj.admin.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.codingapi.tx.annotation.TxTransaction;
import com.pig4cloud.plugin.idempotent.annotation.Idempotent;
import com.ykht.proj.admin.api.dto.UserDTO;
import com.ykht.proj.admin.api.entity.SysUser;
import com.ykht.proj.admin.api.vo.UserVO;
import com.ykht.proj.admin.service.SysUserService;
import com.ykht.proj.common.core.constant.CacheConstants;
import com.ykht.proj.common.core.constant.CommonConstants;
import com.ykht.proj.common.core.constant.SecurityConstants;
import com.ykht.proj.common.core.util.R;
import com.ykht.proj.common.log.annotation.SysLog;
import com.ykht.proj.common.security.annotation.Inner;
import com.ykht.proj.common.security.service.ProjUser;
import com.ykht.proj.common.security.util.SecurityUtils;
import com.ykht.proj.coupon.Enum.UserTypeEnum;
import com.ykht.proj.coupon.api.feign.RemoteBrandService;
import com.ykht.proj.coupon.api.feign.RemoteCompanyService;
import com.ykht.proj.coupon.api.feign.RemoteShopService;
import com.ykht.proj.coupon.api.feign.RemoteUserExtService;
import com.ykht.proj.coupon.dto.UserExtDto;
import com.ykht.proj.coupon.vo.BindSjVo;
import com.ykht.proj.coupon.vo.BindedBrandUserByLoginIdVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.validation.Valid;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author proj
 * @date 2018/12/16
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/user")
@Api(value = "user", tags = "用户管理模块")
@Slf4j
public class SysUserController {

	private final SysUserService userService;
	private final RemoteBrandService remoteBrandService;
	private final RemoteUserExtService remoteUserExtService;

	@Value("${security.encode.key:pigxpigxpigxpigx}")
	private String encodeKey;
	private static final String KEY_ALGORITHM = "AES";


	@ApiOperation(value = "获取用户绑定的商家")
	@PostMapping("/getBindSjList")
	public R<BindSjVo> bindSjList() {
		log.info("->获取用户绑定的商家");
		try {
			Integer userId = SecurityUtils.getUser().getId();
			UserExtDto userExt = new UserExtDto();
			userExt.setUserId(userId);
			userExt.setUserType(SecurityUtils.getUser().getUserType());
			userExt.setStatus(0);//上架
			return userService.bindSjList(userExt);
		} catch (Exception e) {
			e.printStackTrace();
			return R.failed();
		}
	}

	@ApiOperation(value = "切换商家")
	@GetMapping("/changeSj/{sjId}")
	public R changeSj(@PathVariable Long sjId) {
		log.info("->切换商家：{}", sjId);
		UserExtDto userExt = new UserExtDto();
		userExt.setUserId(SecurityUtils.getUserId().intValue());
		userExt.setStatus(0);
		userExt.setSjId(sjId);
		userExt.setUserType(SecurityUtils.getUser().getUserType());
		return userService.changeSj(userExt);
	}

	/**
	 * 获取指定用户全部信息
	 *
	 * @return 用户信息
	 */
	@Inner
	@GetMapping("/info/{username}")
	public R info(@PathVariable String username) {
		SysUser user = userService.getOne(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
		if (user == null) {
			return R.failed(null, String.format("用户信息为空 %s", username));
		}
		return R.ok(userService.findUserInfo(user));
	}

	@PostMapping("ids")
	public List<SysUser> userByIds(@RequestBody List<Long> ids) {
		if (ids.size() == 0) return new ArrayList<>();
		List<SysUser> list = userService.list(Wrappers.<SysUser>query().lambda().in(SysUser::getUserId, ids));
		return list;
	}


	/**
	 * 通过ID串查询用户信息
	 *
	 * @param ids ID串
	 * @return 用户信息
	 */
	@GetMapping("getByIdListUser")
	public Map<Long, String> getByIdListUser(List<Integer> ids) {
		return userService.getUserByIds(ids);
	}

	/**
	 * 通过ID查询用户信息
	 *
	 * @param id ID
	 * @return 用户信息
	 */
	@GetMapping("/{id}")
	public R user(@PathVariable Integer id) {
		return R.ok(userService.selectUserVoById(id));
	}

	/**
	 * 通过ID 查询用户信息
	 *
	 * @return 用户信息
	 */
	@GetMapping("getByIdUser/{id}")
	public UserVO getByIdUser(@PathVariable Long id) {
		SysUser serviceById = userService.getById(id);
		return BeanUtil.toBean(serviceById, UserVO.class);
	}


	/**
	 * 根据用户名查询用户信息
	 *
	 * @param username 用户名
	 * @return
	 */
	@GetMapping("/details/{username}")
	public R user(@PathVariable String username) {
		SysUser condition = new SysUser();
		condition.setUsername(username);
		return R.ok(userService.getOne(new QueryWrapper<>(condition)));
	}

	/**
	 * 删除用户信息
	 *
	 * @param id ID
	 * @return R
	 */
	@SysLog("删除用户信息")
	@GetMapping("deleteUserId")
//	@PreAuthorize("@pms.hasPermission('sys_user_del')")
	@ApiOperation(value = "删除用户", notes = "根据ID删除用户")
	@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "int", paramType = "path")
	public R userDel(Integer id) {
		SysUser sysUser = userService.getById(id);
		if (sysUser.getUserType().equals(UserTypeEnum.company.getValue())
				|| sysUser.getUserType().equals(UserTypeEnum.brand.getValue())
				|| sysUser.getUserType().equals(UserTypeEnum.shop.getValue())
				|| sysUser.getUserType().equals(UserTypeEnum.customer_company.getValue())) {
			R<List> userExt4Inner = remoteUserExtService.getUserExtList(BeanUtil.toBean(sysUser, UserExtDto.class), SecurityConstants.FROM_IN);
			if (userExt4Inner.getCode() != 0) {
				return R.failed(userExt4Inner.getMsg());
			}
			List data = userExt4Inner.getData();
			if (null != data && data.size() > 0) {
				return R.failed("你的" + UserTypeEnum.getDescByVal(sysUser.getUserType()) + "没有解绑完");
			}
		}
		return R.ok(userService.deleteUserById(sysUser));
	}

	/**
	 * 添加用户
	 *
	 * @param userDto 用户信息
	 * @return success/false
	 */
	@SysLog("添加用户")
	@PostMapping
	@PreAuthorize("@pms.hasPermission('sys_user_add')")
	@Idempotent(key = "#userDto.username", expireTime = 1, info = "请勿快速点击")
	public R<UserDTO> user(@RequestBody UserDTO userDto) {
		userDto.setDeptId(1);
		userDto.setCreateUser(SecurityUtils.getUserId().intValue());
		userDto.setLockFlag("0");

//		userDto.setUserType(userDto.getRole()-1);//前端把数据权限去掉了，usertype需要自己填充
		SysUser sysUser = userService.getOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getUsername, userDto.getUsername()).eq(SysUser::getDelFlag, 0));
		if (sysUser != null) return R.failed("用户名已存在！");
		if (StringUtils.isNotBlank(userDto.getPhone())) {
			List<SysUser> userList = userService.list(new QueryWrapper<SysUser>().lambda().eq(SysUser::getPhone, userDto.getPhone()).eq(SysUser::getDelFlag, 0));
			if (userList.size()>0) return R.failed("电话号码已存在");
		}
		Integer loginUserType = SecurityUtils.getUser().getUserType();
		if (loginUserType.equals(UserTypeEnum.company.getValue()) && (userDto.getUserType().equals(UserTypeEnum.company.getValue())
				|| userDto.getUserType().equals(UserTypeEnum.admin.getValue()))) {
			return R.failed("公司只能创建品牌或门店");
		} else if (loginUserType.equals(UserTypeEnum.brand.getValue()) && !userDto.getUserType().equals(UserTypeEnum.shop.getValue())) {
			return R.failed("品牌只能创建门店");
		} else if (loginUserType.equals(UserTypeEnum.shop.getValue())) {
			return R.failed("门店不能创建");
		}
		if (userDto.getUserType().equals(UserTypeEnum.shop.getValue()) && null == userDto.getParentId()) {
			return R.failed("请选择品牌");
		}
		if (userDto.getUserType().equals(UserTypeEnum.brand.getValue()) && null == userDto.getParentId()) {
			return R.failed("公司不能为空");
		}
		SysUser saveUser = userService.saveUser(userDto);
		return R.ok(BeanUtil.toBean(saveUser, UserDTO.class));
	}

	/**
	 * 更新用户信息
	 *
	 * @param userDto 用户信息
	 * @return R
	 */
	@SysLog("更新用户信息")
	@PutMapping
	@PreAuthorize("@pms.hasPermission('sys_user_edit')")
	public R updateUser(@Valid @RequestBody UserDTO userDto) {
		System.out.println(StringUtils.isNotBlank(userDto.getPhone()));
		List<SysUser> list = ListUtil.empty();
		if (StringUtils.isNotBlank(userDto.getPhone()))
			list = userService.list(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getPhone, userDto.getPhone()).ne(SysUser::getUserId, userDto.getUserId()));
		if (list.size() > 0) return R.failed("该手机号已存在！");

		return R.ok(userService.updateUser(userDto));
	}

	/**
	 * 更新用户基本信息
	 *
	 * @param user
	 * @return
	 */
	@ApiOperation(value = "绑定商家的被调用方验证")
	@PostMapping("bindSj")
	public R bindSj(@RequestBody SysUser user) {
		userService.bindSj(user);
		return R.ok();
	}

	@ApiOperation(value = "解绑商家")
	@PostMapping("unBindSj")
	public R unBindSj(@RequestBody SysUser user) {
		userService.unBindSj(user);
		return R.ok();
	}

	/**
	 * 分页查询用户
	 *
	 * @param page    参数集
	 * @param userDTO 查询参数列表
	 * @return 用户集合
	 */
	@GetMapping("/page")
	public R getUserPage(Page page, UserDTO userDTO) {
		log.info("->分页查询用户:{}", JSONUtil.toJsonStr(userDTO));
		Integer userType = SecurityUtils.getUser().getUserType();
		if (userType.equals(UserTypeEnum.company.getValue())) {
//			R<Long> byLoginId = remoteCompanyService.getByLoginId(SecurityUtils.getUserId().toString());
			R<List<Long>> byCompanyId = remoteBrandService.getByCompanyId(SecurityUtils.getSjId().toString());
			List<Long> data = byCompanyId.getData();
			data.add(SecurityUtils.getUserId());
			userDTO.setIds(data);
		}
		if (userType.equals(UserTypeEnum.brand.getValue())) {
			R<List<Long>> byLoginId = remoteBrandService.getByLoginId(SecurityUtils.getSjId().toString());
			List<Long> data = byLoginId.getData();
			data.add(SecurityUtils.getUserId());
			userDTO.setIds(data);
		}
		if (userType.equals(UserTypeEnum.shop.getValue())) {
			List<Long> ids = new ArrayList<>();
			ids.add(SecurityUtils.getUserId());
			userDTO.setIds(ids);
		}
		userDTO.setCreateUser(-1);
		IPage usersPage = userService.getUsersPage(page, userDTO);
		List<UserVO> records = usersPage.getRecords();
		List<UserExtDto> userReqList = new ArrayList<>();
		if (records != null && records.size() > 0) {
			for (UserVO userVO : records) {
				userVO.setType(userVO.getUserType());
//				userVO.setPassword(decrypt(userVO.getPassword()));
				userReqList.add(BeanUtil.toBean(userVO, UserExtDto.class));
			}
		}
		R<HashMap<Integer, List>> userExtDtoMap = remoteUserExtService.getUserExtDtoMapLogingTyoe(userReqList);
		if (records != null && records.size() > 0) {
			for (UserVO userVO : records) {
				userExtDtoMap.getData().forEach((key, value) -> {
					if (userVO.getUserId().equals(key)) {
						userVO.setBindingSj(value);
					}
				});
			}
		}
		HashMap<Integer, List> data = userExtDtoMap.getData();
		return R.ok(usersPage);
	}


	/**
	 * C73 用户列表（平台
	 *
	 * @param page    参数集
	 * @param userDTO 查询参数列表
	 * @return 用户集合
	 */
	@GetMapping("/getAdminList")
	public R getAdminList(Page page, UserDTO userDTO) {
		log.info("->分页查询用户:{}", JSONUtil.toJsonStr(userDTO));
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		if (null != userDTO.getUsername() && !"".equals(userDTO.getUsername())) {
			queryWrapper.lambda().like(SysUser::getUsername, userDTO.getUsername());
		}
		if (null != userDTO.getNickName() && !"".equals(userDTO.getNickName())) {
			queryWrapper.lambda().like(SysUser::getNickName, userDTO.getNickName());
		}
		queryWrapper.lambda().like(SysUser::getUserType, UserTypeEnum.admin.getValue());
		return R.ok(userService.page(page, queryWrapper));
	}


	public String decrypt(String text) {
		AES aes = new AES(Mode.CBC, Padding.NoPadding, new SecretKeySpec(encodeKey.getBytes(), KEY_ALGORITHM),
				new IvParameterSpec(encodeKey.getBytes()));
		// 获取请求密码并解密
		byte[] result = aes.decrypt(Base64.decode(text.getBytes(StandardCharsets.UTF_8)));
		String password = new String(result, StandardCharsets.UTF_8);
		System.out.println(password);
		return password;
	}

	@ApiOperation("根据获取用户：userType0系统管理员 1公司 2品牌 3门店")
	@GetMapping("/listByUserType")
	public R<List<SysUser>> listByUserType(SysUser sysUser) {
//		if (sysUser.getUserType() == 2) { // 是品牌不用管
//			List<SysUser> list = ListUtil.empty();
//			R<BindedBrandUserByLoginIdVo> binded = remoteBrandService.bindedBrandUserByLoginId();
//			if (CommonConstants.SUCCESS == binded.getCode()) {
//				int companyId = binded.getData().getConpanyId().intValue();
//				List<Long> ids = binded.getData().getIds();
//				list = userService.list(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getParentId, companyId).notIn(ids.size() > 0, SysUser::getUserId, ids));
//			}
//			return R.ok(list);
//		}
//		QueryWrapper<SysUser> queryWrapper = new QueryWrapper();
//		queryWrapper.lambda().eq(SysUser::getUserType, sysUser.getUserType())
//				.eq(SysUser::getLockFlag, 0);
//		if (sysUser.getUserType() == 3) {
//			queryWrapper.lambda().eq(SysUser::getParentId, sysUser.getParentId());
//		}
//		List<SysUser> sysUserList = userService.list(queryWrapper);
//		if (sysUserList.size() > 0) {
//			// 用户ID
//			List<Integer> userIdList = new ArrayList<>();
//			sysUserList.stream().forEach(itme -> userIdList.add(itme.getUserId()));
//			Map<String, Object> map = new HashMap<>(3);
//			map.put("userIdList", userIdList);
//			map.put("userType", sysUser.getUserType());
//			map.put("parentId", sysUser.getParentId());
//
//			R<List<Integer>> bindingResources = remoteShopService.getBindingResources(map);
//			List<Integer> list = bindingResources.getData();
//			if (list != null && list.size() > 0) {
//				List<SysUser> userList = userService.list(Wrappers.lambdaQuery(SysUser.class).in(SysUser::getUserId, list));
//				return R.ok(userList);
//			}
//		}

		return R.ok(userService.list(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserType, sysUser.getUserType())));
	}

	/**
	 * 修改个人信息
	 *
	 * @param userDto userDto
	 * @return success/false
	 */
	@SysLog("修改个人信息")
	@PutMapping("/edit")
	public R updateUserInfo(@Valid @RequestBody UserDTO userDto) {
		return userService.updateUserInfo(userDto);
	}

	/**
	 * @param username 用户名称
	 * @return 上级部门用户列表
	 */
	@GetMapping("/ancestor/{username}")
	public R listAncestorUsers(@PathVariable String username) {
		return R.ok(userService.listAncestorUsers(username));
	}


	/**
	 * 获取指定用户全部信息  用户名
	 *
	 * @return 用户信息
	 */
	@GetMapping("/findByUserName/{username}")
	public List<SysUser> findByUserName(@PathVariable String username) {
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(SysUser::getUserType, UserTypeEnum.WAITER.getValue())
				.like(SysUser::getUsername, username);
		return userService.list(queryWrapper);
	}

	/**
	 * 获取指定用户全部信息  用户手机号
	 *
	 * @return 用户信息
	 */
	@GetMapping("/findByUserPhone/{userPhone}")
	public List<SysUser> findByUserPhone(@PathVariable String userPhone) {
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(SysUser::getUserType, UserTypeEnum.WAITER.getValue())
				.like(SysUser::getPhone, userPhone);
		return userService.list(queryWrapper);
	}

	/**
	 * 获取指定用户全部信息  用户名 手机号
	 *
	 * @return 用户信息
	 */
	@GetMapping("/findByUserNameAndUserPhone/{username}")
	public List<SysUser> findByUserNameAndUserPhone(@PathVariable String username) {
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(SysUser::getUserType, UserTypeEnum.WAITER.getValue())
				.like(SysUser::getNickName, username).or().like(SysUser::getPhone, username);
		return userService.list(queryWrapper);
	}

	/**
	 * 获取指定用户全部信息  用户名 手机号
	 *
	 * @return 用户信息
	 */
	@PostMapping("/findByUserNameAndUserPhone4WaiterExtList")
	public List<SysUser> findByUserNameAndUserPhone4WaiterExtList(@RequestBody UserDTO userDto) {
		/*QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		if (null !=  userDto.getNickName()){
			queryWrapper.lambda().like(SysUser::getUsername, userDto.getNickName());
		}
		if (null !=  userDto.getPhone()){
			queryWrapper.lambda().like(SysUser::getPhone, userDto.getPhone());
		}*/
		return userService.list(Wrappers.lambdaQuery(SysUser.class)
				.eq(SysUser::getUserType, UserTypeEnum.WAITER.getValue())
				.like(userDto.getNickName() != null, SysUser::getNickName, userDto.getNickName())
				.eq(userDto.getPhone() != null, SysUser::getPhone, userDto.getPhone()));
	}

	/**
	 * 根据 nikeName 获取指定用户全部信息  用户名
	 *
	 * @return 用户信息
	 */
	@GetMapping("/findByNickName/{nickName}")
	public List<SysUser> findByNickName(@PathVariable String nickName) {
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(SysUser::getUserType, UserTypeEnum.WAITER.getValue())
				.like(SysUser::getNickName, nickName);
		return userService.list(queryWrapper);
	}

	@GetMapping("/getUserByIds")
	public R<List<SysUser>> getUserByIds(@RequestParam("ids") List<Long> ids) {
		if (ids.size() == 0) return R.ok(new ArrayList<>());
		return R.ok(userService.listByIds(ids));
	}

	/**
	 * 根据 username 和 用户类型 获取指定用户全部信息
	 *
	 * @return 用户信息
	 */
	@GetMapping("/getUserList")
	public List<SysUser> getUserList(String username, Integer userType) {
		log.info("->根据 username 和 用户类型 获取指定用户全部信息 :{}", JSONUtil.toJsonStr(username + userType));
		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(SysUser::getUserType, userType);
		if (null != username) {
			queryWrapper.lambda().like(SysUser::getUsername, username).or().eq(SysUser::getUserId, username);
		}
		return userService.list(queryWrapper);
	}


}
